package com.monkeybrother.security.controller;

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Desc
 * @Author houry
 * @Date 2021/4/19 9:33
 **/
public class SensitiveDataConverter extends MessageConverter {

    /**
     * 身份证号正则规则
     */
    private static final String ID_CARD_REGEX = "([1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}(\\d|x|X))";
    /**
     * 手机号正则规则
     */
    private static final String MOBILE_REGEX = "(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}";

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(ID_CARD_REGEX);
        Matcher matcher = pattern.matcher("{\"idCard\":\"411625199703075833\",\"nickName\":\"小猴子\",\"mobile\":1381***1914}");
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            System.out.println(dataDesensitization(matcher.group()));
        }
    }

    /**
     * 对敏感日志进行脱敏
     *
     * @param event ILoggingEvent
     * @return 脱敏后的数据
     */
    @Override
    public String convert(ILoggingEvent event) {
        String message = event.getFormattedMessage();
        return desensitization(message);
    }

    /**
     * 数据脱敏方法
     *
     * @param data 原始数据
     * @return 脱敏后的数据
     */
    private static String desensitization(String data) {
        if (StringUtils.isBlank(data)) return "";
        data = desensitization(data, ID_CARD_REGEX);
        data = desensitization(data, MOBILE_REGEX);
        return data;
    }

    /**
     * 根据正则匹配之后对数据进行脱敏
     *
     * @param data    原始数据
     * @param regular 正则规则
     * @return 脱敏后的数据
     */
    private static String desensitization(String data, String regular) {
        Pattern pattern = Pattern.compile(regular);
        Matcher matcher = pattern.matcher(data);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, dataDesensitization(matcher.group()));
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    private static String dataDesensitization(String data) {
        return dataDesensitization(data, 4, 4, "*");
    }

    private static String dataDesensitization(String data, String replaceChar) {
        return dataDesensitization(data, 4, 4, replaceChar);
    }

    private static String dataDesensitization(String data, int length, String replaceChar) {
        return dataDesensitization(data, length, length, replaceChar);
    }

    /**
     * 对数据脱敏的实际处理逻辑
     *
     * @param data           原始数据
     * @param showHeadLength 展示前几位
     * @param showTailLength 展示后几位
     * @param replaceChar    其他字符的替换
     * @return 脱敏后的数据
     */
    private static String dataDesensitization(String data, int showHeadLength, int showTailLength, String replaceChar) {
        if (StringUtils.isBlank(data)) return "";
        if ((showHeadLength + showTailLength) >= data.length()) return data;
        return StringUtils.left(data, showHeadLength).concat(StringUtils.leftPad(StringUtils.right(data, showTailLength), data.length() - showHeadLength, replaceChar));
    }
}
